package api

import (
	admindao "TaskAssignmentSystem/internal/admin/dao"
	api "TaskAssignmentSystem/internal/admin/services"
	"TaskAssignmentSystem/internal/app/dao"
	"TaskAssignmentSystem/internal/app/services"
	"TaskAssignmentSystem/internal/pkg/middleware/handler"
	"TaskAssignmentSystem/pkg/oss"
	"TaskAssignmentSystem/pkg/utils"
	"errors"
	"fmt"
	"github.com/go-the-way/exl"
	"github.com/kataras/iris/v12"
	"github.com/shopspring/decimal"
	"io/ioutil"
	"os"
	"time"
)

type ReadExcelSalary struct {
	UserId              string  `excel:"用户ID(必填)"`
	RealName            string  `excel:"用户姓名（选填）"`
	NickName            string  `excel:"用户昵称（选填）"`
	BaseSalary          float64 `excel:"用户基础工资（元）(必填)"`
	IncentiveSalary     float64 `excel:"用户激励工资（元）（选填）"`
	SumSalary           float64 `excel:"用户总工资（必填）"`
	ProjectId           string  `excel:"所属项目ID（选填）"`
	Title               string  `excel:"所属项目名称（选填）"`
	Remarks             string  `excel:"答主发放备注(选填)(如工资为0，则系统不提醒)"`
	IsTeamSalary        int     `excel:"团长奖励是否发放（必填），0=不发，1=发"`
	TeamIncentiveSalary float64 `excel:"团长奖励数值（选填)(仅团队提成形式为固定数值需要用到）"`
	TeamRemarks         string  `excel:"团长发放备注(选填)"`
	DetailUrl           string  `excel:"用户详情链接(选填)"`
	DetailUrlTl         string  `excel:"团长详情链接(选填)"`
}

func (*ReadExcelSalary) Configure(rc *exl.ReadConfig) {}

func SalaryImportHandler(ctx iris.Context) {
	//1.解析execl
	_, handle, err := ctx.FormFile("file")

	if err != nil {
		ctx.JSON(utils.ResponseError{Code: iris.StatusInternalServerError, Message: err.Error()})
		return
	}
	file, _ := handle.Open()
	defer file.Close()
	if models, err := exl.Read[*ReadExcelSalary](file); err != nil {
		fmt.Println("read excel err:" + err.Error())
		ctx.JSON(utils.ResponseServerError(errors.New("excel读取错误")))
		return
	} else {
		fmt.Printf("read excel num: %d\n", len(models))
		viewUserSalarys := make([]*admindao.SystemViewUserSalary, 0)
		//viewUserSalarys := make([]*admindao.SystemViewUserSalary, len(models)-1)
		index := 0
		for i, model := range models {
			//从第二行开始读取
			if i == 0 || utils.StringIsEmpty(model.UserId) {
				continue
			}
			viewUserSalary := &admindao.SystemViewUserSalary{}
			viewUserSalary.UserId = model.UserId
			viewUserSalary.RealName = model.RealName
			viewUserSalary.NickName = model.NickName
			viewUserSalary.BaseSalary = model.BaseSalary

			viewUserSalary.IncentiveSalary = model.IncentiveSalary
			viewUserSalary.SumSalary = model.SumSalary
			viewUserSalary.Balance = model.SumSalary * 100
			viewUserSalary.ProjectId = model.ProjectId
			viewUserSalary.Title = model.Title
			viewUserSalary.Remarks = model.Remarks
			viewUserSalary.IsTeamSalary = model.IsTeamSalary
			viewUserSalary.TeamIncentiveSalary = model.TeamIncentiveSalary
			viewUserSalary.TeamRemarks = model.TeamRemarks
			viewUserSalary.DetailUrl = model.DetailUrl
			viewUserSalary.DetailUrlTl = model.DetailUrlTl

			viewUserSalarys = append(viewUserSalarys, viewUserSalary)

			/*viewUserSalarys[index] = &admindao.SystemViewUserSalary{}

			viewUserSalarys[index].UserId = model.UserId
			viewUserSalarys[index].RealName = model.RealName
			viewUserSalarys[index].NickName = model.NickName
			viewUserSalarys[index].BaseSalary = model.BaseSalary

			viewUserSalarys[index].IncentiveSalary = model.IncentiveSalary
			viewUserSalarys[index].SumSalary = model.SumSalary
			viewUserSalarys[index].Balance = model.SumSalary * 100
			viewUserSalarys[index].ProjectId = model.ProjectId
			viewUserSalarys[index].Title = model.Title
			viewUserSalarys[index].Remarks = model.Remarks
			viewUserSalarys[index].IsTeamSalary = model.IsTeamSalary
			viewUserSalarys[index].TeamIncentiveSalary = model.TeamIncentiveSalary
			viewUserSalarys[index].TeamRemarks = model.TeamRemarks
			viewUserSalarys[index].DetailUrl = model.DetailUrl*/
			index++
		}
		var salaryService api.SalaryService
		go salaryService.UserSalaryExeclImport(viewUserSalarys, handle.Filename)
		ctx.JSON(utils.ResponseOK())
	}
}

type SalaryUserQueryRequest struct {
	BaseRequest
	FileId          uint   `json:"file_id"`
	FileTitle       string `json:"file_title"`
	UploadTimeStart string `json:"upload_time_start"`
	UploadTimeEnd   string `json:"upload_time_end"`
}

func QueryUserSalaryFile(ctx iris.Context) {
	var RequestParams SalaryUserQueryRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	param := map[string]interface{}{}
	if utils.StringIsNotEmpty(RequestParams.UploadTimeStart) {
		param["upload_time_start"] = RequestParams.UploadTimeStart
	}
	if utils.StringIsNotEmpty(RequestParams.UploadTimeEnd) {
		param["upload_time_end"] = RequestParams.UploadTimeEnd
	}
	if utils.StringIsNotEmpty(RequestParams.FileTitle) {
		param["file_title"] = RequestParams.FileTitle
	}
	var salaryService api.SalaryService
	if total, list, err := salaryService.QueryUserSalaryFile(RequestParams.Page, RequestParams.PageSize, param); err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	} else {
		ctx.JSON(utils.ResponseData(iris.Map{"count": total, "list": list}))
		return
	}
}
func SalaryUserQueryHandler(ctx iris.Context) {
	var RequestParams SalaryUserQueryRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var salaryService api.SalaryService
	if total, list, err := salaryService.QueryUserSalary(RequestParams.FileId, RequestParams.Page, RequestParams.PageSize); err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	} else {
		resMap := map[string]interface{}{}
		if _, l, err := salaryService.QueryUserSalary(RequestParams.FileId, 1, -1); err != nil {
			ctx.JSON(utils.ResponseServerError(err))
			return
		} else {
			resMap["totalCount"] = len(l)
			successCount := 0
			var baseSalary decimal.Decimal
			var incentiveSalary decimal.Decimal
			var sumSalary decimal.Decimal
			var teamSalary decimal.Decimal
			for _, salary := range l {
				if salary.NickName != "(未查到此用户)" {
					successCount++
				}
				baseSalary = baseSalary.Add(decimal.NewFromFloat(salary.BaseSalary))
				incentiveSalary = incentiveSalary.Add(decimal.NewFromFloat(salary.IncentiveSalary))
				sumSalary = sumSalary.Add(decimal.NewFromFloat(salary.SumSalary))
				teamSalary = teamSalary.Add(decimal.NewFromFloat(salary.TeamSalary))
			}
			resMap["successCount"] = successCount
			resMap["baseSalary"] = baseSalary
			resMap["incentiveSalary"] = incentiveSalary
			resMap["sumSalary"] = sumSalary
			resMap["teamSalary"] = teamSalary

			/*var tlService dao.Common[admindao.SystemViewTeamUserSalary]
			tlService.First(map[string]interface{}{"file_id": RequestParams.FileId})*/
		}
		ctx.JSON(utils.ResponseData(iris.Map{"count": total, "list": list, "totalMap": resMap}))
		return
	}
}

/*
	func SalaryTeamUserQueryHandler(ctx iris.Context) {
		var RequestParams SalaryUserQueryRequest
		if err := ctx.ReadJSON(&RequestParams); err != nil {
			handler.ArgumentErrorHandle(err, ctx)
			return
		}
		var salaryService api.SalaryService
		if total, list, err := salaryService.QueryTeamUserSalary(RequestParams.FileId, RequestParams.Page, RequestParams.PageSize); err != nil {
			ctx.JSON(utils.ResponseServerError(err))
			return
		} else {
			ctx.JSON(utils.ResponseData(iris.Map{"count": total, "list": list}))
			return
		}
	}
*/
/*
func PlaceOnFileSalaryUserQueryHandler(ctx iris.Context) {
	var RequestParams SalaryUserQueryRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var salaryService api.SalaryService
	if total, list, err := salaryService.QueryUserSalaryPlaceOnFile(RequestParams.UserId, RequestParams.Page, RequestParams.PageSize); err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	} else {
		ctx.JSON(utils.ResponseData(iris.Map{"count": total, "list": list}))
		return
	}

}
*/
/*
func PlaceOnFileSalaryTeamUserQueryHandler(ctx iris.Context) {
	var RequestParams SalaryUserQueryRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var salaryService api.SalaryService
	if total, list, err := salaryService.QueryTeamUserSalaryPlaceOnFile(RequestParams.UserId, RequestParams.Page, RequestParams.PageSize); err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	} else {
		ctx.JSON(utils.ResponseData(iris.Map{"count": total, "list": list}))
		return
	}
}
*/

func PayOffSalaryUserHandler(ctx iris.Context) {
	var RequestParams SalaryUserQueryRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var salaryService api.SalaryService
	err := salaryService.SalaryUserPlaceOnFile(RequestParams.FileId)
	if err == nil {
		ctx.JSON(utils.ResponseOK())
	} else {
		ctx.JSON(utils.ResponseServerError(err))
	}
}

func PayOffSalaryUserReturnHandler(ctx iris.Context) {
	var RequestParams SalaryUserQueryRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var salaryService api.SalaryService
	err := salaryService.SalaryUserPlaceOnFileReturn(RequestParams.FileId)
	if err == nil {
		ctx.JSON(utils.ResponseOK())
	} else {
		ctx.JSON(utils.ResponseServerError(err))
	}
}

func PayOffSalaryTeamUserHandler(ctx iris.Context) {
	var RequestParams SalaryUserQueryRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var salaryService api.SalaryService
	err := salaryService.SalaryTeamUserPlaceOnFile(RequestParams.FileId)
	if err == nil {
		ctx.JSON(utils.ResponseOK())
	} else {
		ctx.JSON(utils.ResponseServerError(err))
	}
}

func PayOffSalaryTeamUserReturnHandler(ctx iris.Context) {
	var RequestParams SalaryUserQueryRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var salaryService api.SalaryService
	err := salaryService.SalaryTeamUserPlaceOnFileReturn(RequestParams.FileId)
	if err == nil {
		ctx.JSON(utils.ResponseOK())
	} else {
		ctx.JSON(utils.ResponseServerError(err))
	}
}

type DeleteUserSalaryRequest struct {
	Id uint `json:"id" validate:"required"`
}

func DeleteUserSalaryHandler(ctx iris.Context) {
	var RequestParams DeleteUserSalaryRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}
	var serveFile admindao.Common[admindao.SystemUserSalaryFile]
	serveFile.Query = map[string]interface{}{"id": RequestParams.Id}
	if _, err := serveFile.First(map[string]interface{}{"id": RequestParams.Id}); err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	}

	var serve admindao.Common[admindao.SystemViewUserSalary]
	serve.Query = map[string]interface{}{"salary_file_id": RequestParams.Id}
	if err := serve.RemoveUnscopedWhere(serve.Query).Error; err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	} else {
		serveFile.RemoveUnscopedWhere(serveFile.Query)
		ctx.JSON(utils.ResponseOK())
		return
	}
}

type ExportUserSalary struct {
	Id               uint    `excel:"序号"`
	CreatedAt        string  `excel:"上传时间"`
	UserStatus       string  `excel:"用户支付状态"`
	TeamStatus       string  `excel:"团长支付状态"`
	No               uint    `excel:"编号"`
	UserId           string  `excel:"用户ID"`
	RealName         string  `excel:"用户姓名"`
	NickName         string  `excel:"用户昵称"`
	BaseSalary       float64 `excel:"用户基础工资（元）"` //用户基础工资
	IncentiveSalary  float64 `excel:"用户激励工资（元）"` //用户激励工资
	SumSalary        float64 `excel:"用户总工资"`     //用户总工资
	Balance          float64 `excel:"用户芝草数"`     //用户芝草
	ProjectId        string  `excel:"所属项目ID"`    //所属项目id
	Title            string  `excel:"所属项目名称"`    //所属项目名称
	Remarks          string  `excel:"答主发放备注"`    //答主发放备注
	Phone            string  `excel:"用户手机号"`
	Email            string  `excel:"用户邮箱"`
	IsTeamSalary     int     `excel:"团长奖励（必填），0=不发，1=发"` //团长奖励是否发放，0 不发;1 发;
	TeamRemarks      string  `excel:"团长发放备注(选填)"`        //团长发放备注
	TeamUserId       string  `excel:"团长ID"`              //团长用户id
	TeamRealName     string  `excel:"团长姓名"`              //团长用户姓名
	TeamNickName     string  `excel:"团长昵称"`              //团长用户昵称
	TeamSalary       float64 `excel:"团长工资"`              //团长金额
	TeamBalance      float64 `excel:"团长芝草"`              //团长芝草
	TeamNumber       string  `excel:"团队编号"`              //团队编号
	Level            int64   `excel:"团队等级"`              //团队等级
	TeamPhone        string  `excel:"团长手机号"`             //团长手机号
	TeamEmail        string  `excel:"团长邮箱"`              //团长邮箱
	UserGrantTime    string  `excel:"用户发放时间"`            //用户发放时间
	TeamGrantTime    string  `excel:"团长发放时间"`            //团长发放时间
	UserWithdrawTime string  `excel:"用户撤回时间"`            //用户撤回时间
	TeamWithdrawTime string  `excel:"团长撤回时间"`            //团长撤回时间
}

type ExportUserSalaryRequest struct {
	FileId int `json:"file_id" validate:"required"` //文件ID
}

func (*ExportUserSalary) Configure(rc *exl.WriteConfig) {}
func ExportUserSalaryHandler(ctx iris.Context) {
	var RequestParams ExportUserSalaryRequest
	if err := ctx.ReadJSON(&RequestParams); err != nil {
		handler.ArgumentErrorHandle(err, ctx)
		return
	}

	var salaryFileServe dao.Common[admindao.SystemUserSalaryFile]
	if file, err := salaryFileServe.First(map[string]interface{}{"id": RequestParams.FileId}); err != nil {
		ctx.JSON(utils.ResponseServerError(err))
		return
	} else {
		type SystemViewUserSalary struct {
			admindao.SystemViewUserSalary
			Phone string `json:"phone"`
			Email string `json:"email"`
		}
		var userSalaryServe services.CommonService[SystemViewUserSalary]
		field := "tas_system_view_user_salary.*,tas_system_user.phone,tas_system_user.email"
		userSalaryServe.SelectField = &field
		userSalaryServe.LeftJoin = append(userSalaryServe.LeftJoin, fmt.Sprintf("left join tas_system_user on tas_system_view_user_salary.user_id = tas_system_user.user_id "))
		userSalaryServe.WhereStr = append(userSalaryServe.WhereStr, fmt.Sprintf("salary_file_id = %d ", RequestParams.FileId))
		userSalaryServe.PageSize = -1
		if userSalary, err := userSalaryServe.SelectList(); err != nil {
			ctx.JSON(utils.ResponseServerError(err))
			return
		} else {
			exportLists := make([]*ExportUserSalary, len(userSalary.Data))
			for i, export := range userSalary.Data {
				exportLists[i] = &ExportUserSalary{}
				exportLists[i].Id = file.Id
				exportLists[i].CreatedAt = file.CreatedAt.Format("2006-01-02 15:04:05")
				if file.UserStatus > 0 {
					exportLists[i].UserStatus = "用户已支付"
				} else {
					exportLists[i].UserStatus = "用户未支付"
				}
				if file.TeamStatus > 0 {
					exportLists[i].TeamStatus = "团长已支付"
				} else {
					exportLists[i].TeamStatus = "团长未支付"
				}
				exportLists[i].No = export.Id
				exportLists[i].UserId = export.UserId
				exportLists[i].RealName = export.RealName
				exportLists[i].NickName = export.NickName
				exportLists[i].BaseSalary = export.BaseSalary
				exportLists[i].IncentiveSalary = export.IncentiveSalary
				exportLists[i].SumSalary = export.SumSalary
				exportLists[i].Balance = export.Balance
				exportLists[i].ProjectId = export.ProjectId
				exportLists[i].Title = export.Title
				exportLists[i].Remarks = export.Remarks
				exportLists[i].Phone = export.Phone
				exportLists[i].Email = export.Email
				exportLists[i].IsTeamSalary = export.IsTeamSalary
				exportLists[i].TeamRemarks = export.TeamRemarks
				exportLists[i].TeamUserId = export.TeamUserId
				exportLists[i].TeamRealName = export.TeamRealName
				exportLists[i].TeamNickName = export.TeamNickName
				exportLists[i].TeamSalary = export.TeamSalary
				exportLists[i].TeamBalance = export.TeamBalance
				exportLists[i].TeamNumber = export.TeamNumber
				exportLists[i].Level = export.Level
				exportLists[i].TeamPhone = export.TeamPhone
				exportLists[i].TeamEmail = export.TeamEmail
				if export.UserGrantTime.Format("2006-01-02 15:04:05") == "0001-01-01 00:00:00" {
					exportLists[i].UserGrantTime = ""
				} else {
					exportLists[i].UserGrantTime = export.UserGrantTime.Format("2006-01-02 15:04:05")
				}
				if export.TeamGrantTime.Format("2006-01-02 15:04:05") == "0001-01-01 00:00:00" {
					exportLists[i].TeamGrantTime = ""
				} else {
					exportLists[i].TeamGrantTime = export.TeamGrantTime.Format("2006-01-02 15:04:05")
				}
				if export.UserWithdrawTime.Format("2006-01-02 15:04:05") == "0001-01-01 00:00:00" {
					exportLists[i].UserWithdrawTime = ""
				} else {
					exportLists[i].UserWithdrawTime = export.UserWithdrawTime.Format("2006-01-02 15:04:05")
				}
				if export.TeamWithdrawTime.Format("2006-01-02 15:04:05") == "0001-01-01 00:00:00" {
					exportLists[i].TeamWithdrawTime = ""
				} else {
					exportLists[i].TeamWithdrawTime = export.TeamWithdrawTime.Format("2006-01-02 15:04:05")
				}
			}

			unix := time.Now().UnixNano()
			if err := exl.Write(fmt.Sprintf("./export/export_user_salary_records_%d.xlsx", unix), exportLists); err != nil {
				fmt.Println("write excel err:" + err.Error())
				return
			}
			tempFilename := fmt.Sprintf("./export/export_user_salary_records_%d.xlsx", unix)
			//删除本地临时文件
			defer os.Remove(tempFilename)
			bucketClient := oss.BucketClient{}
			readFile, _ := ioutil.ReadFile(fmt.Sprintf("./export/export_user_salary_records_%d.xlsx", unix))
			bucketClient.UpBytes(readFile, fmt.Sprintf("task-assign/export/export_user_salary_records_%d.xlsx", unix))
			ctx.JSON(utils.Response{Code: iris.StatusOK, Message: iris.StatusText(iris.StatusOK), Data: fmt.Sprintf("%s/task-assign/export/export_user_salary_records_%d.xlsx", utils.ServerConf.AliOssConf.CallBackHost, unix)})
			return
		}
	}
	ctx.JSON(utils.ResponseOK())
	return
}
